/***********************************************************************************
Copy right:	    hqyj Tech.
Author:         jiaoyue
Date:           2023.07.01
Description:    http请求处理
***********************************************************************************/

#include <sys/types.h>
#include <sys/socket.h>

#include "custom_handle.h"
#include "thttpd.h"
#include "cJSON.h"
#include "shmem.h"
#include "msg_queue_peer.h"

#define KB 1024
#define HTML_SIZE (64 * KB)

// 普通的文本回复需要增加html头部
#define HTML_HEAD "Content-Type: text/html\r\n" \
                  "Connection: close\r\n"

struct data_shm
{
    int data_int_bool[7];
    float data_float[4];
};

union data
{
    int a;
    float val;
};
struct stm32_data
{
    long a;
    int key;
    int type;
    union data val;
};
struct modbus_data
{
    long a;
    int type;
    int addr;
    int key;
    union data val;
};
struct stm32_data stm32data;
struct modbus_data modbusdata;

char data_html[1024];
struct data_shm data_coll;

static int handle_login(int sock, const char *input)
{
    char reply_buf[HTML_SIZE] = {0};
    char *uname = strstr(input, "username=");
    uname += strlen("username=");
    char *p = strstr(input, "password");
    *(p - 1) = '\0';
    printf("username = %s\n", uname);

    char *passwd = p + strlen("password=");
    printf("passwd = %s\n", passwd);

    if (strcmp(uname, "admin") == 0 && strcmp(passwd, "admin") == 0)
    {
        sprintf(reply_buf, "<script>localStorage.setItem('usr_user_name', '%s');</script>", uname);
        strcat(reply_buf, "<script>window.location.href = '/index.html';</script>");
        send(sock, reply_buf, strlen(reply_buf), 0);
    }
    else
    {
        printf("web login failed\n");

        //"用户名或密码错误"提示，chrome浏览器直接输送utf-8字符流乱码，没有找到太好解决方案，先过渡
        char out[128] = {0xd3, 0xc3, 0xbb, 0xa7, 0xc3, 0xfb, 0xbb, 0xf2, 0xc3, 0xdc, 0xc2, 0xeb, 0xb4, 0xed, 0xce, 0xf3};
        sprintf(reply_buf, "<script charset='gb2312'>alert('%s');</script>", out);
        strcat(reply_buf, "<script>window.location.href = '/login.html';</script>");
        send(sock, reply_buf, strlen(reply_buf), 0);
    }

    return 0;
}

static int handle_add(int sock, const char *input)
{
    int number1, number2;

    // input必须是"data1=1data2=6"类似的格式，注意前端过来的字符串会有双引号
    sscanf(input, "\"data1=%ddata2=%d\"", &number1, &number2);
    printf("num1 = %d\n", number1);

    char reply_buf[HTML_SIZE] = {0};
    printf("num = %d\n", number1 + number2);
    sprintf(reply_buf, "%d", number1 + number2);
    printf("resp = %s\n", reply_buf);
    send(sock, reply_buf, strlen(reply_buf), 0);

    return 0;
}

/*------------------------------------------------------------------------*/

static int Refresh_data(int sock, const char *input)
{
    // 获取共享内存数据
    struct shm_param para;
    // 初始化共享内存
    shm_init(&para, "mqtt_json", 1024);
    // 取出数据
    char *p_shm = shm_getaddr(&para);
    // p_shm = "{"
    //         "\"version\":\"v1.0\","
    //         "\"report\":{\"type\":0,\"period\":5},"
    //         "\"stm32\":{\"data\":["
    //         "{\"key\":101,\"name\":\"Temp\",\"type\":3,\"value\":20.3,\"newval\":30.56},"
    //         "{\"key\":102,\"name\":\"Door\",\"type\":1,\"value\":1,\"newval\":0},"
    //         "{\"key\":103,\"name\":\"Led1\",\"type\":1,\"value\":0,\"newval\":0},"
    //         "{\"key\":104,\"name\":\"Led2\",\"type\":1,\"value\":0,\"newval\":0},"
    //         "{\"key\":105,\"name\":\"Fan\",\"type\":1,\"value\":0,\"newval\":1},"
    //         "{\"key\":106,\"name\":\"Ekey\",\"type\":1,\"value\":0,\"newval\":1},"
    //         "{\"key\":107,\"name\":\"Hum\",\"type\":3,\"value\":20.3,\"newval\":33.9}"
    //         "]},"
    //         "\"modbus\":{\"data\":["
    //         "{\"key\":201,\"name\":\"Etemp\",\"addr\":30000,\"type\":3,\"value\":20.3,\"newval\":30.6},"
    //         "{\"key\":202,\"name\":\"Revolution\",\"addr\":30001,\"type\":1,\"value\":0,\"newval\":3000},"
    //         "{\"key\":203,\"name\":\"Carbon\",\"addr\":30002,\"type\":3,\"value\":0.04,\"newval\":30.56},"
    //         "{\"key\":204,\"name\":\"Mdoor\",\"addr\":40000,\"type\":1,\"value\":1,\"newval\":0}"
    //         "]}}";
    // 解析数据
    cJSON *root;
    root = cJSON_Parse(p_shm);
    if (!root)
    {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL)
        {
            fprintf(stderr, "ERROR before :%s\n", error_ptr);
        }
        return 1;
    }

    // 解析stm32数据
    cJSON *stm32 = cJSON_GetObjectItem(root, "stm32");
    cJSON *stm32_data = cJSON_GetObjectItem(stm32, "data");

    // 遍历数据项
    for (int i = 0; i < cJSON_GetArraySize(stm32_data); i++)
    {
        cJSON *item = cJSON_GetArrayItem(stm32_data, i);
        cJSON *key = cJSON_GetObjectItem(item, "key");
        cJSON *newval = cJSON_GetObjectItem(item, "newval");
        switch (key->valueint)
        {
        case 101:
            data_coll.data_float[0] = newval->valuedouble;
            break;
        case 102:
            data_coll.data_int_bool[0] = newval->valueint;
            break;
        case 103:
            data_coll.data_int_bool[1] = newval->valueint;
            break;
        case 104:
            data_coll.data_int_bool[2] = newval->valueint;
            break;
        case 105:
            data_coll.data_int_bool[3] = newval->valueint;
            break;
        case 106:
            data_coll.data_int_bool[4] = newval->valueint;
            break;
        case 107:
            data_coll.data_float[1] = newval->valuedouble;
            break;

        default:
            break;
        }
    }

    // 解析modbus数据

    cJSON *modbus = cJSON_GetObjectItem(root, "modbus");
    cJSON *modbus_data = cJSON_GetObjectItem(modbus, "data");

    // 遍历数据项
    for (int i = 0; i < cJSON_GetArraySize(modbus_data); i++)
    {
        cJSON *item = cJSON_GetArrayItem(modbus_data, i);
        cJSON *key = cJSON_GetObjectItem(item, "key");
        cJSON *newval = cJSON_GetObjectItem(item, "newval");
        switch (key->valueint)
        {
        case 201:
            data_coll.data_float[2] = newval->valuedouble;
            break;
        case 202:
            data_coll.data_int_bool[5] = newval->valueint;
            break;
        case 203:
            data_coll.data_float[3] = newval->valuedouble;
            break;
        case 204:
            data_coll.data_int_bool[6] = newval->valueint;
            break;

        default:
            break;
        }
    }
    // 打印data_int_bool数组
    for (int i = 0; i < 7; i++)
    {
        printf("data_int_bool[%d]:%d\n", i, data_coll.data_int_bool[i]);
    }
    // 打印data_float数组

    for (int i = 0; i < 4; i++)
    {
        printf("data_float[%d]:%.2f\n", i, data_coll.data_float[i]);
    }

    // 拼接到data_html字符串数组中
    snprintf(data_html, sizeof(data_html), "%.2f°C/%d/%d/%d/%d/%d/%.2f/%.2f°C/%d/%.2f/%d/",
             // stm32
             data_coll.data_float[0],
             data_coll.data_int_bool[0],
             data_coll.data_int_bool[1],
             data_coll.data_int_bool[2],
             data_coll.data_int_bool[3],
             data_coll.data_int_bool[4],
             data_coll.data_float[1],
             // modbus
             data_coll.data_float[2],
             data_coll.data_int_bool[5],
             data_coll.data_float[3],
             data_coll.data_int_bool[6]);

    // 打印data_html字符串数组
    printf("data_html:%s\n", data_html);

    cJSON_Delete(root);
    // 发送给浏览器端
    send(sock, data_html, strlen(data_html), 0);

    return 0;
}

/*________________________________________________________________*/

static int upTemp(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct stm32_data upTemp;

    // 设置消息类型
    upTemp.a = 1;
    // 设置key值
    upTemp.key = 101;
    //设置数据类型
    upTemp.type = 3;
    // 设置value值
    upTemp.val.val = 35.00;
    // 消息队列发送消息
    msg_queue_send("queue", &upTemp, sizeof(upTemp), upTemp.a);

    return 0;
}

static int downTemp(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct stm32_data downTemp;

    // 设置消息类型
    downTemp.a = 1;
    // 设置key值
    downTemp.key = 101;
    // 设置数据类型
    downTemp.type = 3;
    // 设置value值
    downTemp.val.val = 15.00;
    // 消息队列发送消息
    msg_queue_send("queue", &downTemp, sizeof(downTemp), downTemp.a);

    printf("%.2f\n", downTemp.val.val);
    return 0;
}

static int upHum(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct stm32_data upHum;

    // 设置消息类型
    upHum.a = 1;
    // 设置key值
    upHum.key = 107;
    // 设置数据类型
    upHum.type = 3;
    // 设置value值
    upHum.val.val = 50.00;
    // 消息队列发送消息
    msg_queue_send("queue", &upHum, sizeof(upHum), upHum.a);

    printf("%.2f\n", upHum.val.val);
    return 0;
}

static int downHum(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct stm32_data downHum;

    // 设置消息类型
    downHum.a = 1;
    // 设置key值
    downHum.key = 107;
    // 设置数据类型
    downHum.type = 3;
    // 设置value值
    downHum.val.val = 15.00;
    // 消息队列发送消息
    msg_queue_send("queue", &downHum, sizeof(downHum), downHum.a);

    printf("%.2f\n", downHum.val.val);

    return 0;
}



//灯二,实验室工作状态
static int onLed2(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct stm32_data onLed2;

    // 设置消息类型
    onLed2.a = 1;
    // 设置key值
    onLed2.key = 104;
    //设置数据类型
    onLed2.type = 1;
    // 设置value值
    onLed2.val.a = 1;
    // 消息队列发送消息
    msg_queue_send("queue", &onLed2, sizeof(onLed2), onLed2.a);

    return 0;
}

static int offLed2(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct stm32_data offLed2;

    // 设置消息类型
    offLed2.a = 1;
    // 设置key值
    offLed2.key = 104;
    // 设置数据类型
    offLed2.type = 1;
    // 设置value值
    offLed2.val.a = 0;
    // 消息队列发送消息
    msg_queue_send("queue", &offLed2, sizeof(offLed2), offLed2.a);
    return 0;
}

static int onFan(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct stm32_data onFan;

    // 设置消息类型
    onFan.a = 1;
    // 设置key值
    onFan.key = 105;
    // 设置数据类型
    onFan.type = 1;
    // 设置value值
    onFan.val.a = 1;
    // 消息队列发送消息
    msg_queue_send("queue", &onFan, sizeof(onFan), onFan.a);
    return 0;
}

static int offFan(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct stm32_data offFan;

    // 设置消息类型
    offFan.a = 1;
    // 设置key值
    offFan.key = 105;
    // 设置数据类型
    offFan.type = 1;
    // 设置value值
    offFan.val.a = 0;
    // 消息队列发送消息
    msg_queue_send("queue", &offFan, sizeof(offFan), offFan.a);
    return 0;
}

//急停按钮,灯3表示
static int onEkey(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct stm32_data onEkey;

    // 设置消息类型
    onEkey.a = 1;
    // 设置key值
    onEkey.key = 106;
    // 设置数据类型
    onEkey.type = 1;
    // 设置value值
    onEkey.val.a = 1;
    // 消息队列发送消息
    msg_queue_send("queue", &onEkey, sizeof(onEkey), onEkey.a);

    return 0;
}

static int offEkey(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct stm32_data offEkey;

    // 设置消息类型
    offEkey.a = 1;
    // 设置key值
    offEkey.key = 106;
    // 设置数据类型
    offEkey.type = 1;
    // 设置value值
    offEkey.val.a = 0;
    // 消息队列发送消息
    msg_queue_send("queue", &offEkey, sizeof(offEkey), offEkey.a);
    return 0;
}

static int upRevolution(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct modbus_data upRevolution;

    // 设置消息类型
    upRevolution.a = 2;
    // 设置key值
    upRevolution.key = 202;
    //设置地址值
    upRevolution.addr=30001;
    //设置数据类型
    upRevolution.type=1;
    // 设置value值
    upRevolution.val.a = 1000;
    // 消息队列发送消息
    msg_queue_send("queue", &upRevolution, sizeof(upRevolution), upRevolution.a);

    return 0;
}

static int downRevolution(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct modbus_data downRevolution;

    // 设置消息类型
    downRevolution.a = 2;
    // 设置key值
    downRevolution.key = 202;
    //设置地址值
    downRevolution.addr=30001;
    //设置数据类型
    downRevolution.type=1;
    // 设置value值
    downRevolution.val.a = 500;
    // 消息队列发送消息
    msg_queue_send("queue", &downRevolution, sizeof(downRevolution), downRevolution.a);

    return 0;
}

static int onMdoor(int sock, const char *input)
{
    // 初始化消息队列结构体变量
    struct modbus_data onMdoor;

    // 设置消息类型
    onMdoor.a = 2;
    // 设置key值
    onMdoor.key = 204;
    //设置地址值
    onMdoor.addr=40000;
    //设置数据类型
    onMdoor.type=1;
    // 设置value值
    onMdoor.val.a = 1;
    // 消息队列发送消息
    
    msg_queue_send("queue", &onMdoor, sizeof(onMdoor), onMdoor.a);

    return 0;
}

static int offMdoor(int sock, const char *input)
{
    
    // 初始化消息队列结构体变量
    struct modbus_data offMdoor;
    memset(&offMdoor,0,sizeof(offMdoor));
    // 设置消息类型
    offMdoor.a = 2;
    // 设置key值
    offMdoor.key = 204;
    //设置地址值
    offMdoor.addr=40000;
    //设置数据类型
    offMdoor.type=1;
    // 设置value值
    offMdoor.val.a = 0;
    // 消息队列发送消息
    
    msg_queue_send("queue", &offMdoor, sizeof(offMdoor), offMdoor.a);
   
    return 0;
}

/*------------------------------------------------------------------------*/

/**
 * @brief 处理自定义请求，在这里添加进程通信
 * @param input
 * @return
 */
int parse_and_process(int sock, const char *query_string, const char *input)
{
    // query_string不一定能用的到

    // 先处理登录操作
    if (strstr(input, "username=") && strstr(input, "password="))
    {
        return handle_login(sock, input);
    }
    // 处理求和请求
    else if (strstr(input, "data1=") && strstr(input, "data2="))
    {
        return handle_add(sock, input);
    }

    /*------------------------------------------------------------------------*/

    // 处理主页页面请刷新数据请求
    else if (strstr(input, "updata"))
    {
        return Refresh_data(sock, input);
    }

    // stm32温度阈值增加
    else if (strstr(input, "upTemp"))
    {
        return upTemp(sock, input);
    }

    // stm32温度阈值减少
    else if (strstr(input, "downTemp"))
    {
        return downTemp(sock, input);
    }

    // stm32湿度阈值增加
    else if (strstr(input, "upHum"))
    {
        return upHum(sock, input);
    }

    // stm32湿度阈值减少
    else if (strstr(input, "downHum"))
    {
        return downHum(sock, input);
    }

    // modbus转速增加
    else if (strstr(input, "upRevolution"))
    {
        return upRevolution(sock, input);
    }

    // modbus转速减少
    else if (strstr(input, "downRevolution"))
    {
        return downRevolution(sock, input);
    }



    // stm32LED2 开--实验室状态
    else if (strstr(input, "onLed2"))
    {
        return onLed2(sock, input);
    }

    // stm32LED2 关
    else if (strstr(input, "offLed2"))
    {
        return offLed2(sock, input);
    }

    // stm32风扇 开
    else if (strstr(input, "onFan"))
    {
        return onFan(sock, input);
    }

    // stm32风扇 关
    else if (strstr(input, "offFan"))
    {
        return offFan(sock, input);
    }

    // stm32Ekey 开--急停按键,灯模拟
    else if (strstr(input, "onEkey"))
    {
        return onEkey(sock, input);
    }

    // stm32Ekey 关
    else if (strstr(input, "offEkey"))
    {
        return offEkey(sock, input);
    }

    // modbus Mdoor 开
    else if (strstr(input, "onMdoor"))
    {
        return onMdoor(sock, input);
    }

    // modbus Mdoor 关
    else if (strstr(input, "offMdoor"))
    {
        return offMdoor(sock, input);
    }

    /*------------------------------------------------------------------------*/

    else // 剩下的都是json请求，这个和协议有关了
    {
        // 构建要回复的JSON数据
        const char *json_response = "{\"message\": \"Hello, client!\"}";

        // 发送HTTP响应给客户端
        send(sock, json_response, strlen(json_response), 0);
    }

    return 0;
}
